﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;

namespace CSharp.Libs.Koc.KernelModels
{
    public class KocReloader
    {
        #region declarations
        private Kernel _AB = null;
        private Timer _tmrReload = new Timer();

        private Int32 _intReloadServerId = 0;

        public const Int32 MAX_SERVER_NUMBER = 999999;

        #region events
        public delegate void ReloadServerEventHandler(object sender, ReloadServerEventArgs e);
        public event ReloadServerEventHandler ReloadServer;
        private void ThrowReloadServerEvent(Int32 ServerId)
        {
            if (ReloadServer != null)
            {
                ReloadServer(this, new ReloadServerEventArgs(ServerId));
            }
        }

        public delegate void ReloadServerIdChangedEventHandler(object sender);
        public event ReloadServerIdChangedEventHandler ReloadServerIdChanged;
        private void ThrowReloadServerIdChangedEvent()
        {
            if (ReloadServerIdChanged != null)
            {
                ReloadServerIdChanged(this);
            }
        }
        #endregion
        #endregion



        #region constructor / terminator
        public KocReloader(
            Kernel AB)
        {
            _AB = AB;

            _AB.TM.SeedReceived += new TrafficMonitor.SeedReceivedEventHandler(TM_SeedReceived);
            
            _tmrReload.Elapsed += new ElapsedEventHandler(_tmrReload_Elapsed);

            Int32.TryParse(_AB.LAO.GetOption(constants.LAO_DEFAULT_SERVER_ID), out _intReloadServerId);
            ThrowReloadServerIdChangedEvent();

            Int32 intReloadTimeout = 60;
            Int32.TryParse(_AB.LAO.GetOption(constants.LAO_KOC_RELOAD_TIMEOUT), out intReloadTimeout);
            _tmrReload.Interval = intReloadTimeout * 1000;
        }

        ~KocReloader()
        {
            if (_tmrReload.Enabled)
            {
                _tmrReload.Stop();
            }
            _tmrReload.Elapsed -= _tmrReload_Elapsed;
            _tmrReload.Dispose();
            _tmrReload = null;

            if(_AB != null)
            {
                if(_AB.TM != null)
                {
                    _AB.TM.SeedReceived -= TM_SeedReceived;
                }
                _AB = null;
            }
        }
        #endregion



        #region event handling
        void TM_SeedReceived(object sender, SeedReceivedEventArgs srea)
        {
            if (_tmrReload.Enabled)
            {
                _tmrReload.Stop();
            }
        }

        void _tmrReload_Elapsed(object sender, ElapsedEventArgs e)
        {
            _Reload(_intReloadServerId);
        }
        #endregion



        #region private functions
        private void _Reload(
            Int32 ServerId)
        {
            try
            {
                ThrowReloadServerEvent(ServerId);

                if (!_tmrReload.Enabled)
                {
                    _tmrReload.Start();
                }
            }
            catch (Exception ex)
            {
                _AB.EC.AddException(ex, this.ToString(), _AB.EC.Tools.GetCurrentMethodName());
            }
        }
        #endregion



        #region interface
        #region properties
        public Int32 ReloadServerId
        {
            get
            {
                return _intReloadServerId;
            }
            set
            {
                if(value > 0 && value <= MAX_SERVER_NUMBER)
                {
                    _intReloadServerId = value;
                    _AB.LAO.SetOption(constants.LAO_DEFAULT_SERVER_ID, _intReloadServerId.ToString());
                    ThrowReloadServerIdChangedEvent();
                }
            }
        }
        #endregion

        #region methods
        public void Reload()
        {
            _Reload(_intReloadServerId);
        }

        public void Reload(
            Int32 ServerId)
        {
            _Reload(ServerId);
        }
        #endregion
        #endregion
    }
}
